package neuronvisualizer;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.awt.BorderLayout;
/**
 *
 * @author alex
 */

public class TimelineGUI extends javax.swing.JFrame {

    private Timeline tline;
    private Timer tmer;
    private int time;
    private Driver parent;
    private ArrayList<Integer> sparkList;
    private ArrayList<Section> sectionSparkList;
    private class TaskPerformer implements ActionListener{
        public void actionPerformed(ActionEvent evt){
            statLabel.setText(""+time);
                if(time < 10000){
                	while(sparkList.size() > 0){
                		int id = sparkList.get(0);
                		parent.getNeuron(id).unspark();
                		sparkList.remove(0);
                	}
                	while(sectionSparkList.size()>0){
                		sectionSparkList.get(0).unspark();
                		sectionSparkList.remove(0);
                	}
                    time++;
                    jSlider1.setValue(time);
                    ArrayList<Integer> spikeIDs = tline.isSpiking((long)time);
                    if(spikeIDs != null){
                    	for (int i : spikeIDs){
                    		if(parent.getNeuron(i).getModel()!=null){
                    			parent.getNeuron(i).spark();	
                    			sparkList.add(i);
                    		}           
                    		else{
                    			Section temp = parent.getSectionOfNeuron(parent.getNeuron(i));
                    			temp.spark();
                    			sectionSparkList.add(temp);
                    		}
                    	}	
                    }
                }
                else{
                    pause();
                }
        }
    }
    /** Creates new form TimelineGUI */
    public TimelineGUI(Driver p, String path) {
    	sparkList = new ArrayList<Integer>();
    	sectionSparkList = new ArrayList<Section>();
        time = 0;
        parent = p;
        initComponents();
        //ActionListener which moves time forward every time it receives
        //an event from tmer
        TaskPerformer t = new TaskPerformer();
        //TODO: add a method to change the delay on tmer
        tmer = new Timer(100, t);

        tline = new Timeline(path);
    }
    
    public void setTime(int x){
        time = x;
        jSlider1.setValue(time);
        ArrayList<Integer> spikeIDs = tline.isSpiking((long)time);
        while(sparkList.size() > 0){
    		int id = sparkList.get(0);
    		parent.getNeuron(id).unspark();
    		sparkList.remove(0);
    	}
        if(spikeIDs != null){
        	for(int i : spikeIDs){
	            parent.getNeuron(i).spark();
	            sparkList.add(i);
        	}    
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jSlider1 = new javax.swing.JSlider();
        playButton = new javax.swing.JToggleButton();
        timeField = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        timeButton = new javax.swing.JButton();
        statLabel = new javax.swing.JLabel();
        spikeLabel = new javax.swing.JLabel();
        histoPanel = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jSlider1.setMajorTickSpacing(10);
        jSlider1.setMaximum(10000);
        jSlider1.setMinorTickSpacing(1);
        jSlider1.setPaintTicks(true);
        jSlider1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                jSlider1MousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                jSlider1MouseReleased(evt);
            }
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jSlider1MouseClicked(evt);
            }
        });
        jSlider1.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSlider1StateChanged(evt);
            }
        });

        playButton.setText("Play");
        playButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                playButtonActionPerformed(evt);
            }
        });

        jLabel1.setText("Time (ms)");

        timeButton.setText("Go To Time");
        timeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                timeButtonActionPerformed(evt);
            }
        });

        statLabel.setText("0");

        spikeLabel.setText("No spike");
        
        javax.swing.GroupLayout histoPanelLayout = new javax.swing.GroupLayout(histoPanel);
        histoPanel.setLayout(new BorderLayout());
        histoPanelLayout.setHorizontalGroup(
            histoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 414, Short.MAX_VALUE)
        );
        histoPanelLayout.setVerticalGroup(
            histoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 201, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(playButton, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(statLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 32, Short.MAX_VALUE)
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(timeField, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(1, 1, 1)
                .addComponent(timeButton)
                .addContainerGap())
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jSlider1, javax.swing.GroupLayout.DEFAULT_SIZE, 385, Short.MAX_VALUE)
                .addGap(17, 17, 17))
            .addGroup(layout.createSequentialGroup()
                .addGap(162, 162, 162)
                .addComponent(spikeLabel)
                .addContainerGap(236, Short.MAX_VALUE))
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(histoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(histoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(spikeLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(playButton)
                    .addComponent(timeField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1)
                    .addComponent(timeButton)
                    .addComponent(statLabel)))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void timeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeButtonActionPerformed
        try{setTime(Integer.parseInt(timeField.getText()));}
        catch(NumberFormatException e){
            System.err.print("Input must be a number");
        }
    }//GEN-LAST:event_timeButtonActionPerformed

    private void playButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_playButtonActionPerformed
        
        if (tmer.isRunning()){
        	playButton.setText("Play");
            pause();
        }
        else{
        	playButton.setText("Pause");
            tmer.start();
        }
    }//GEN-LAST:event_playButtonActionPerformed

    private void jSlider1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider1MouseClicked
        pause();
    }//GEN-LAST:event_jSlider1MouseClicked

    private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSlider1StateChanged
        // TODO: add code to communicate with Visual/Timeline when slider moves
        statLabel.setText(""+jSlider1.getValue());
    }//GEN-LAST:event_jSlider1StateChanged

    private void jSlider1MouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider1MouseReleased
        time = jSlider1.getValue();
        ArrayList<Integer> spikeIDs = tline.isSpiking((long)time);
        while(sparkList.size() > 0){
    		int id = sparkList.get(0);
    		parent.getNeuron(id).unspark();
    		sparkList.remove(0);
    	}
        if(spikeIDs != null){
        	for(int i : spikeIDs){
	            parent.getNeuron(i).spark();
	            sparkList.add(i);
        	}    
        }
    }//GEN-LAST:event_jSlider1MouseReleased

    private void jSlider1MousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jSlider1MousePressed
        pause();
    }//GEN-LAST:event_jSlider1MousePressed
    public void pause(){
        tmer.stop();
    }
    public Timeline getTimeline(){
    	return tline;
    }
    public JPanel getHistoPanel(){
    	return histoPanel;
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel histoPanel;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JSlider jSlider1;
    private javax.swing.JToggleButton playButton;
    private javax.swing.JLabel spikeLabel;
    private javax.swing.JLabel statLabel;
    private javax.swing.JButton timeButton;
    private javax.swing.JTextField timeField;
    // End of variables declaration//GEN-END:variables

}
